package com.yungu.swift.system.sys.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.model.PageVo;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.lbs.model.param.FenceParam;
import com.yungu.swift.lbs.model.vo.FenceVo;
import com.yungu.swift.lbs.service.FenceService;
import com.yungu.swift.system.sys.dao.SysBusinessOrganizationMapper;
import com.yungu.swift.system.sys.dao.SysPointSiteMapper;
import com.yungu.swift.system.sys.dao.SysSiteFenceMapper;
import com.yungu.swift.system.sys.dao.SysWayMapper;
import com.yungu.swift.system.sys.model.dto.SysFenceDto;
import com.yungu.swift.system.sys.model.dto.SysPointSiteDto;
import com.yungu.swift.system.sys.model.dto.SysSiteFenceDto;
import com.yungu.swift.system.sys.model.param.AdminSiteFenceParam;
import com.yungu.swift.system.sys.model.param.AdminWayPageParam;
import com.yungu.swift.system.sys.model.vo.AdminSystemPointSiteVo;
import com.yungu.swift.system.sys.model.vo.SiteFenceInfoVo;
import com.yungu.swift.system.sys.service.SysCityService;
import com.yungu.swift.system.sys.service.SysPointSiteService;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * SystemPointSiteServiceImpl
 **/

@Slf4j
@Service
public class SysPointSiteServiceImpl implements SysPointSiteService {
    @Autowired
    private SysPointSiteMapper sysPointSiteMapper;
    @Autowired
    private SysWayMapper systemWayMapper;
    @Autowired
    private SysBusinessOrganizationMapper sysBusinessOrganizationMapper;
    @Autowired
    private SysCityService sysCityService;
    @Reference
    private FenceService fenceService;
    @Autowired
    private SysSiteFenceMapper sysSiteFenceMapper;

    @Override
    public ResponseData<PageVo<AdminSystemPointSiteVo>> queryPage(AdminWayPageParam wayPageParam) {
        PageBounds pageBounds = new PageBounds(wayPageParam.getPageNum(), wayPageParam.getPageSize());
        Map<String, Object> map = MapUtils.convertObjToMap(wayPageParam);
        map.put("state", CommonConstant.STATE_NORMAL);
        map.put("adminAgentUuid", wayPageParam.getUserCompanyUuid());
        map.put("adminCompanyUuid", wayPageParam.getUserCompanyUuid());
        PageList<AdminSystemPointSiteVo> pageList = sysPointSiteMapper.queryPageVo(map, pageBounds);
        PageVo<AdminSystemPointSiteVo> pageVo = new PageVo(wayPageParam.getPageNum(), wayPageParam.getPageSize(),
                pageList.getPaginator().getTotalCount());
        pageVo.setItems(pageList);
        return ResponseData.buildSuccessResponse(pageVo);
    }

    @Override
    public ResponseData<SysPointSiteDto> findOne(Map<String, Object> params) {
        List<SysPointSiteDto> list = sysPointSiteMapper.list(params);
        if (list != null && list.size() > 0) {
            return ResponseData.buildSuccessResponse(list.get(0));
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查无符合条件");
    }

    @Override
    public ResponseData<List<SysPointSiteDto>> findByIds(List<String> uuids) {
        return ResponseData.buildSuccessResponse("获取线路终点成功", sysPointSiteMapper.findByIds(MapUtils.build(
                "uuids", uuids)));
    }

    @Override
    public ResponseData<List<SysPointSiteDto>> findOrigins(Map<String, Object> map) {
        List<SysPointSiteDto> origins = sysPointSiteMapper.findOrigins(map);
        if (null != origins && origins.size() > 0) {
            return ResponseData.buildSuccessResponse("获取起点成功", origins);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无起点");
    }

    @Override
    public ResponseData<List<SysPointSiteDto>> findByOrderDri(Map<String, Object> map) {
        List<SysPointSiteDto> origins = sysPointSiteMapper.findByOrderDri(map);
        if (null != origins && origins.size() > 0) {
            return ResponseData.buildSuccessResponse("获取订单对应起点成功", origins);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无数据");
    }

    @Override
    public ResponseData<List<SysPointSiteDto>> list(Map<String, Object> map) {
        return ResponseData.buildSuccessResponse(sysPointSiteMapper.list(map));
    }


    @Override
    public ResponseData<Boolean> updateStatus(String uuid, Integer status) {
        //线路判断
        if (CommonConstant.STATUS_CLOSED.equals(status)) {
            Map<String, Object> paras = new HashMap(8);
            paras.put("originSiteUuid", uuid);
            paras.put("destSiteUuid", uuid);
            paras.put("status", CommonConstant.STATUS_OPENED);
            int countExistedWays = systemWayMapper.countExistedWaysByPointSiteStatus(paras);
            if (countExistedWays > 0) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "操作失败：存在正在使用的线路包该起&终点");
            }
        }
        if (sysPointSiteMapper.updateStatus(uuid, status) > 0) {
            return ResponseData.buildSuccessResponse("操作成功，状态已修改", Boolean.TRUE);
        }
        return ResponseData.buildSuccessResponse("操作失败，数据未更新", Boolean.FALSE);
    }

    @Override
    public ResponseData<Boolean> updateState(String uuid, Integer state) {
        //线路判断
        if (CommonConstant.STATE_DEL.equals(state)) {
            Map paras = new HashMap();
            paras.put("originSiteUuid", uuid);
            paras.put("destSiteUuid", uuid);
            paras.put("state", CommonConstant.STATE_NORMAL);
            int countExistedWays = systemWayMapper.countExistedWaysByPointSiteState(paras);
            if (countExistedWays > 0) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "操作失败：存在正在使用的线路包该起&终点");
            }
        }
        if (sysPointSiteMapper.updateState(uuid, state) > 0) {
            if (CommonConstant.STATE_DEL.equals(state)) {
                List<SiteFenceInfoVo> fenceInfoVos = sysSiteFenceMapper.queryFenceInfo(uuid);
                if (CollectionUtils.isNotEmpty(fenceInfoVos)) {
                    sysSiteFenceMapper.delBySiteUuid(uuid);
                    for (SiteFenceInfoVo siteFenceInfoVo : fenceInfoVos) {
                        fenceService.deleteFence(siteFenceInfoVo.getFenceGid());
                    }
                }
            }
            return ResponseData.buildSuccessResponse("操作成功，状态已修改", Boolean.TRUE);
        }
        return ResponseData.buildSuccessResponse("操作失败，数据未更新", Boolean.FALSE);
    }

    @Override
    public ResponseData<Map<String, Object>> saveOrUpdate(SysPointSiteDto site, List<AdminSiteFenceParam> fenceList) {
        //验证名称
        Map<String, Object> paras = new HashMap(8);
        paras.put("name", site.getName());
        //存在校验
        paras.clear();
        paras.put("uuid", site.getUuid());
        paras.put("name", site.getName());
        paras.put("state", CommonConstant.STATE_NORMAL);
        int countExisted = sysPointSiteMapper.countExisted(paras);
        if (countExisted > 0) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "名称已存在");
        }
        //城市开通校验
        paras.clear();
        //获取已开通城市 —— 由于开通区域代理、公司线路时默认其开通平台下所有城市，故在此只过滤平台属性
        paras.put("organizationUuid", site.getAppid());
        paras.put("type", CommonConstant.BUSINESS_TYPE_POOL);
        paras.put("city", site.getCityName());
        int existed = sysBusinessOrganizationMapper.countBusinessOrganization(paras);
        if (existed <= 0) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "操作失败：当前城市未开通跨城业务");
        }
        //保存
        if (StringUtils.isEmpty(site.getUuid())) {
            site.setUuid(StringUtils.buildUUID());
            site.setState(CommonConstant.STATE_NORMAL);
            site.setStatus(CommonConstant.STATUS_OPENED);
            sysPointSiteMapper.add(site);
        } else {
            sysPointSiteMapper.edit(site);
        }
        Map<String, Object> resultMap = saveFence(fenceList, site.getUuid());
        return ResponseData.buildSuccessResponse(resultMap);
    }

    private Map<String, Object> saveFence(List<AdminSiteFenceParam> fenceList, String siteUuid) {
        List<SiteFenceInfoVo> fenceInfoVos = sysSiteFenceMapper.queryFenceInfo(siteUuid);
        Map<String, String> gidMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(fenceList)) {
            for (AdminSiteFenceParam adminSiteFenceParam : fenceList) {
                gidMap.put(adminSiteFenceParam.getFenceGid(), null);
            }
        }
        if (CollectionUtils.isNotEmpty(fenceInfoVos)) {
            log.info("删除围栏：{}", siteUuid);
            sysSiteFenceMapper.delBySiteUuid(siteUuid);
            for (SiteFenceInfoVo siteFenceInfoVo : fenceInfoVos) {
                //如果围栏已存在 则只做更新操作
                if (!gidMap.containsKey(siteFenceInfoVo.getFenceGid())) {
                    ResponseData delFenceRsd = fenceService.deleteFence(siteFenceInfoVo.getFenceGid());
                    log.info("删除围栏结果{},{}", delFenceRsd.getMsg(), siteUuid);
                } else {
                    log.info("围栏已存在,不删除{},{}", siteFenceInfoVo.getFenceGid(), siteUuid);
                }

            }
        }
        StringBuilder msg = new StringBuilder();
        boolean isSuccess = true;
        if (CollectionUtils.isNotEmpty(fenceList)) {
            List<SysSiteFenceDto> saveFenceList = new ArrayList<>();
            for (AdminSiteFenceParam adminSiteFenceParam : fenceList) {
                SysSiteFenceDto sysSiteFenceDto = new SysSiteFenceDto();
                SysFenceDto sysFenceDto = new SysFenceDto();
                FenceParam fenceParam = new FenceParam();
                BeanUtils.copyProperties(adminSiteFenceParam, sysFenceDto);
                BeanUtils.copyProperties(sysFenceDto, fenceParam);
                BeanUtils.copyProperties(sysFenceDto, sysSiteFenceDto);

                sysSiteFenceDto.setUuid(StringUtils.buildUUID());
                sysSiteFenceDto.setSiteUuid(siteUuid);
                sysSiteFenceDto.setCreateOn(new Date());

                //围栏ID不为空时 作更新操作 为空时做新增操作
                if (StringUtils.isEmpty(adminSiteFenceParam.getFenceGid())) {
                    ResponseData<String> responseData = fenceService.addFence(fenceParam);
                    if (!responseData.isSuccess() || StringUtils.isEmpty(responseData.getData())) {
                        log.info("围栏错误：{}", responseData.getMsg());
                        isSuccess = false;
                        msg.append("、").append(adminSiteFenceParam.getFenceName());
                        continue;
                    }
                    log.info("新增围栏结果{},{}", responseData.getMsg(), siteUuid);
                    sysSiteFenceDto.setFenceGid(responseData.getData());
                    saveFenceList.add(sysSiteFenceDto);
                } else {
                    ResponseData<Boolean> responseData = fenceService.updateFence(fenceParam);
                    if (!responseData.isSuccess()) {
                        log.info("围栏错误：{}", responseData.getMsg());
                        isSuccess = false;
                        msg.append("、").append(adminSiteFenceParam.getFenceName());
                        continue;
                    }
                    log.info("保存围栏结果{},{}", responseData.getMsg(), siteUuid);
                    saveFenceList.add(sysSiteFenceDto);
                }
            }

            if (saveFenceList.size() > 0) {
                log.info("保存围栏到数据库,{}", siteUuid);
                sysSiteFenceMapper.addBatch(saveFenceList);
            }
        }
        Map<String, Object> resultMap = new HashMap<>();
        //部分未成功
        if (!isSuccess) {
            resultMap.put("success", false);
            resultMap.put("msg", "围栏" + msg.substring(1) + "存在经纬度重复的情况，请重新编辑");
            return resultMap;
        }
        resultMap.put("success", true);
        return resultMap;
    }

    @Override
    public ResponseData<List<SysPointSiteDto>> findOriginsByQueue(Map<String, Object> paras) {
        List<SysPointSiteDto> origins = sysPointSiteMapper.findOriginsByQueue(paras);
        if (null != origins && origins.size() > 0) {
            return ResponseData.buildSuccessResponse("获取司机排队起点成功", origins);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "无司机排队起点");
    }

    @Override
    public ResponseData<Boolean> checkFence(Double lng, Double lat, String siteUuid) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("siteUuid", siteUuid);
        List<SysSiteFenceDto> fenceList = sysSiteFenceMapper.list(paramMap);
        //点位没有创建围栏 验证通过
        if (CollectionUtils.isEmpty(fenceList)) {
            return ResponseData.buildSuccessResponse(true);
        }
        List<FenceVo> fenceVos = fenceService.statusFence(lng, lat, "861144047871995").getData();
        if (CollectionUtils.isNotEmpty(fenceVos)) {
            List<String> gidList = fenceVos.stream().filter(fenceVo -> "in".equals(fenceVo.getStatus())).map(fenceVo ->
                    fenceVo.getFenceGid()).collect(Collectors.toList());
            for (SysSiteFenceDto sysSiteFenceDto : fenceList) {
                if (gidList.contains(sysSiteFenceDto.getFenceGid())) {
                    log.info("位置点{}进入围栏", siteUuid);
                    return ResponseData.buildSuccessResponse(true);
                }
            }
        }
        log.info("位置点{}校验不通过", siteUuid);
        return ResponseData.buildErrorResponse(0, "未进入运营范围");
    }

    @Override
    public ResponseData<List<SysPointSiteDto>> allByOrganization(Map<String, Object> paramMap) {
        paramMap.put("state", CommonConstant.STATE_NORMAL);
        paramMap.put("status", CommonConstant.STATUS_OPENED);
        return ResponseData.buildSuccessResponse(sysPointSiteMapper.allByOrganization(paramMap));
    }
}